
Imports std

Public Module wordbreaker

    Friend WithEvents config As configMonitor

    Public Enum chartypeDef
        space
        mark
        hanzi
        alphabet
        unknown
    End Enum

    Friend Function initial() As Boolean
        assert(Not config Is Nothing, "config is nothing before initial.")
        'do not need to initialize now
        Return True
    End Function

    Public Function initial(ByRef inputConfig As configMonitor) As Boolean
        config = inputConfig
        Return initial()
    End Function

    Public Function chartype(ByVal c As Char) As chartypeDef
        If isspace(c) Then
            Return chartypeDef.space
        ElseIf language.english.isalpha(c) OrElse language.english.sbc.isalpha(c) Then
            Return chartypeDef.alphabet
        ElseIf language.CJKShare.isCJKHanzi(c) Then
            Return chartypeDef.hanzi
        ElseIf ismark(c) Then
            Return chartypeDef.mark
        Else
            Return chartypeDef.unknown
        End If
    End Function

    Friend Function sentenceBreak(ByRef content As String _
                                            , ByRef sentences As vector(Of pair(Of String, chartypeDef))) As Boolean
        If sentences Is Nothing Then
            sentences = New vector(Of pair(Of String, chartypeDef))
        Else
            sentences.clear()
        End If

        Dim sentence As String
        Dim lasttype As chartypeDef
        Dim i As Int32
        sentence = Nothing
        lasttype = chartypeDef.unknown
        For i = 0 To strlen(content) - 1
            Dim thistype As chartypeDef
            thistype = chartype(content(i))
            If thistype = lasttype AndAlso lasttype <> chartypeDef.unknown Then
                sentence += content(i)
            Else
                If Not isemptystring(sentence) Then
                    assert(sentences.push_back(make_pair(sentence, lasttype)) _
                            , "sentences.push_back(make_pair(sentence,lasttype)) returns false.")
                    sentence = content(i)
                End If
                lasttype = thistype
            End If
        Next

        Return True
    End Function

    Friend Function alphabetbreak(ByRef sentence As String _
                                , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        assert(Not words Is Nothing, "words is nothing before alphabetbreak.")
        assert(words.push_back(make_pair(sentence.ToLower(), chartypeDef.alphabet)) _
            , "words.push_back(make_pair(sentence, chartypeDef.alphabet))")
        Return True
    End Function

    Friend Function hanzibreak(ByRef sentence As String _
                                , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        assert(Not words Is Nothing, "words is nothing before hanzibreak.")
        assert(words.push_back(make_pair(sentence, chartypeDef.hanzi)) _
            , "words.push_back(make_pair(sentence, chartypeDef.hanzi))")
        Return True
    End Function

    Friend Function markbreak(ByRef sentence As String _
                            , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        assert(Not words Is Nothing, "words is nothing before markbreak.")
        assert(words.push_back(make_pair(sentence, chartypeDef.mark)) _
          , "words.push_back(make_pair(sentence, chartypeDef.mark))")
        Return True
    End Function

    Friend Function spacebreak(ByRef sentence As String _
                                , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        assert(Not words Is Nothing, "words is nothing before spacebreak.")
        assert(words.push_back(make_pair(sentence, chartypeDef.space)) _
         , "words.push_back(make_pair(sentence, chartypeDef.space))")
        Return True
    End Function

    Friend Function unknownbreak(ByRef sentence As String _
                                , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        assert(Not words Is Nothing, "words is nothing before unknownbreak.")
        assert(words.push_back(make_pair(sentence, chartypeDef.unknown)) _
          , "words.push_back(make_pair(sentence, chartypeDef.unknown))")
        Return True
    End Function

    Friend Function wordbreak(ByRef sentence As pair(Of String, chartypeDef) _
                            , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        If words Is Nothing Then
            words = New vector(Of pair(Of String, chartypeDef))
        Else
            words.clear()
        End If

        Select Case sentence.second
            Case chartypeDef.alphabet
                Return alphabetbreak(sentence.first, words)
            Case chartypeDef.hanzi
                Return hanzibreak(sentence.first, words)
            Case chartypeDef.mark
                Return markbreak(sentence.first, words)
            Case chartypeDef.space
                Return spacebreak(sentence.first, words)
            Case chartypeDef.unknown
                Return unknownbreak(sentence.first, words)
            Case Else
                Return False
        End Select
    End Function

    Public Function break(ByRef content As String _
                        , ByRef words As vector(Of pair(Of String, chartypeDef))) As Boolean
        If words Is Nothing Then
            words = New vector(Of pair(Of String, chartypeDef))
        Else
            words.clear()
        End If

        Dim sentences As vector(Of pair(Of String, chartypeDef)) = Nothing
        If sentenceBreak(content, sentences) Then
            Dim temp As vector(Of pair(Of String, chartypeDef)) = Nothing
            Dim i As Int32
            For i = 0 To sentences.size() - 1
                If wordbreak(sentences(i), temp) Then
                    assert(words.push_back(temp), "words.push_back(temp) returns false.")
                Else
                    raiseError("cannot break to word of " + sentences(i).first _
                                + ", charType" + Convert.ToString(sentences(i).second) + ", add to words directly." _
                                , errorHandle.errorType.warning)
                    assert(words.push_back(sentences(i)), "words.push_back(sentences(i)) returns false.")
                End If
            Next
            Return True
        Else
            Return False
        End If
    End Function

    Sub New()
        config = Nothing
    End Sub

    Private Sub config_ConfigChanged() Handles config.ConfigChanged
        initial()
    End Sub

    Public Sub unittest()

    End Sub
End Module
